﻿namespace Blaze.Editor
{
    using System.Collections;

    /// <summary>
    /// 用于编辑器的协同程序。
    /// </summary>
    public class EditorCoroutine
    {
        /// <summary>
        /// 获取协同程序本身。
        /// </summary>
        public IEnumerator Fiber { get; private set; }

        /// <summary>
        /// 获取一个值，表示协同程序是否正在执行。
        /// </summary>
        public bool IsRunning
        {
            get { return !IsStopping; }
        }

        /// <summary>
        /// 获取一个值，表示协同程序是否正在停止。
        /// </summary>
        public bool IsStopping { get; private set; }

        public EditorCoroutine(IEnumerator fiber)
        {
            Fiber = fiber;
        }

        /// <summary>
        /// 执行协同程序的下一个步骤，若协同程序结束则返回false，否则返回true。
        /// </summary>
        public bool Next()
        {
            var current = Fiber.Current as EditorCoroutine;
            var isWaiting = current != null && current.IsRunning;
            if (isWaiting)
                return true;

            if (Fiber.MoveNext())
                return true;

            Stop();
            return false;
        }

        /// <summary>
        /// 同步执行协同程序，直到其结束。
        /// </summary>
        /// <returns></returns>
        public bool NextSync()
        {
            var current = Fiber.Current as EditorCoroutine;
            if (current != null && current.IsRunning)
            {
                while (current.NextSync()) ;
            }
            return Fiber.MoveNext();
        }

        /// <summary>
        /// 停止协同程序。
        /// </summary>
        public void Stop()
        {
            var current = Fiber.Current as EditorCoroutine;
            var isWaiting = current != null && current.IsRunning;
            if (isWaiting)
                current.Stop();
            IsStopping = true;
        }

        /// <summary>
        /// 同步执行协同程序，直到其结束。
        /// </summary>
        /// <returns></returns>
        public void Sync()
        {
            while (NextSync()) ;
        }
    }
}